package com.by.toolkit.utils;

import cn.hutool.core.collection.CollectionUtil;

import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author Tian Wei
 * @version 1.0
 * @date 2024/1/11 3:29 PM
 */
public class ChainUtil {


    public static <E, R extends Comparable<? super R>> E getTree(E chain, List<E> allDataList, Function<E, R> parentDeptIdGetFunc, Function<E, R> deptIdGetFunc, BiConsumer<E, List<E>> childListSetFunc, R rootId) {
        allDataList.sort(Comparator.comparing(deptIdGetFunc));
        //父类排序
        Map<R, List<E>> parentIdAndObjsMap = allDataList.stream().collect(Collectors.groupingBy(parentDeptIdGetFunc));
        childListSetFunc.accept(chain, parentIdAndObjsMap.getOrDefault(rootId, Collections.emptyList()));
        for (E next : allDataList) {
            childListSetFunc.accept(next, parentIdAndObjsMap.getOrDefault(deptIdGetFunc.apply(next), Collections.emptyList()));
        }
        return chain;
    }

    public static <E, R extends Comparable<? super R>> List<E> getTreeList(
            List<E> allDataList,
            Function<E, R> parentIdGetFunc,
            Function<E, R> IdGetFunc,
            BiConsumer<E, List<E>> childListSetFunc) {
        if (CollectionUtil.isEmpty(allDataList)) {
            return Collections.emptyList();
        }
        //父类排序
        Map<R, List<E>> parentIdAndObjsMap = allDataList.stream().collect(Collectors.groupingBy(parentIdGetFunc));
        for (E next : allDataList) {
            childListSetFunc.accept(next, parentIdAndObjsMap.getOrDefault(IdGetFunc.apply(next), Collections.emptyList()));
        }
        return parentIdAndObjsMap.entrySet().stream().min(Map.Entry.comparingByKey()).map(Map.Entry::getValue).orElse(Collections.emptyList());
    }

    public static <E, R extends Comparable<? super R>, S extends Comparable<? super S>> List<E> getTreeList(
            List<E> allDataList,
            Function<E, R> parentIdGetFunc,
            Function<E, R> IdGetFunc,
            BiConsumer<E, List<E>> childListSetFunc,
            Function<E, S> sortExtractor) {
        if (CollectionUtil.isEmpty(allDataList)) {
            return Collections.emptyList();
        }
        //父类排序
        Map<R, List<E>> parentIdAndObjsMap = Objects.nonNull(sortExtractor)
                ? allDataList.stream().collect(Collectors.groupingBy(parentIdGetFunc
                , Collectors.collectingAndThen(Collectors.toList(), items -> items.stream()
                        .sorted(Comparator.comparing(sortExtractor, Comparator.naturalOrder()))
                        .collect(Collectors.toList()))))
                : allDataList.stream().collect(Collectors.groupingBy(parentIdGetFunc));
        for (E next : allDataList) {
            childListSetFunc.accept(next, parentIdAndObjsMap.getOrDefault(IdGetFunc.apply(next), Collections.emptyList()));
        }
        return parentIdAndObjsMap.entrySet().stream().min(Map.Entry.comparingByKey()).map(Map.Entry::getValue).orElse(Collections.emptyList());
    }
}
